package com.shangyueshang.thread;

import cn.hutool.core.util.IdUtil;
import com.shangyueshang.common.LogConst;
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;
import org.springframework.util.ObjectUtils;

/**
 * @author: JokeyZheng
 * @email: zhengjingfeng@ruqimobility.com
 * @created: 2022/10/9 12:49
 * @version: v1.0.0
 * <p>
 * 异步线程池任务装饰器
 * 子线程同步父线程的LogId
 * </p>
 */
@Slf4j
public class MDCTaskDecorator implements TaskDecorator {

    @Override
    public Runnable decorate(Runnable runnable) {
        Map<String, String> mdcMap = MDC.getCopyOfContextMap();
        return () -> {
            try {
                if (mdcMap != null) {
                    MDC.setContextMap(mdcMap);
                }
                //变量名称与com.gac.toyota.fcv.common.log.LogAspect内保持一致保持一致
                String logId = MDC.get(LogConst.LOG_ID);
                String username = MDC.get(LogConst.USERNAME);
                if (ObjectUtils.isEmpty(logId)) {
                    logId = IdUtil.objectId();
                    MDC.put(LogConst.LOG_ID, logId);
                    MDC.put(LogConst.USERNAME, Optional.ofNullable(username).orElse(LogConst.SYSTEM));
                }
                runnable.run();
            } catch (Exception ex) {
                log.error("Uncaught executor exception:", ex);
                //如果继续抛出异常，会导致该线程死亡，后续的任务会根据线程池大小创建新线程来执行
                throw ex;
            } finally {
                MDC.clear();
            }
        };
    }
}
